package com.ld.task;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

/**
 * 计算数组中所有元素的和,传递给主线程(分而治之,同步调用)
 * 类似于二分法的用法
 */
public class UserForJoinByRecursiveTask extends RecursiveTask<Integer> {
    private final int THRESHOLD = MakeArray.length / 10;
    private int[] src;
    private int fromIndex;
    private int toIndex;

    public UserForJoinByRecursiveTask(int[] src, int fromIndex, int toIndex) {
        this.src = src;
        this.fromIndex = fromIndex;
        this.toIndex = toIndex;
    }

    @Override
    protected Integer compute() {
        int sum = 0;
        if (toIndex - fromIndex < THRESHOLD) {
            for (int i=fromIndex;i<=toIndex;i++){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                sum += src[i];
            }
            return sum;
        } else {
            //fromIndex.....mid.....toIndex
            int mid = (fromIndex+toIndex)/2; //这只是一种分的方式，也可以分解多个，数量不固定,invokeAll()方法支持数组、集合参数
            UserForJoinByRecursiveTask left = new UserForJoinByRecursiveTask(src,fromIndex,mid);
            UserForJoinByRecursiveTask right = new UserForJoinByRecursiveTask(src,mid,toIndex);
            invokeAll(left,right);
            return left.join()+right.join();
        }
    }

    public static void main(String[] args) {
        ForkJoinPool pool = new ForkJoinPool(6);
        UserForJoinByRecursiveTask task = new UserForJoinByRecursiveTask(MakeArray.getArr(),0,MakeArray.length-1);
        long start = System.currentTimeMillis();
        System.out.println(123);
        pool.invoke(task);
        System.out.println(456);
        Integer sum = task.join();
        System.out.println(789);
        long end = System.currentTimeMillis();
        System.out.println("数组的和是"+sum+",forkJoin消耗的时间是"+(end-start));
        start = System.currentTimeMillis();
        int sum2 = 0;
        for (int num:MakeArray.getArr()) {
            sum2+=num;
        }
        end = System.currentTimeMillis();
        System.out.println("数组的和是"+sum+",普通循环消耗的时间是"+(end-start));
    }

    static class MakeArray {
        public final static int length = 10000; //按需使用，,如果长度不太长不建议使用线程。cpu上下文切换消耗时间
        public static int[] getArr() {
            int[] arr = new int[length];
            for (int i = 0; i < arr.length; i++) {
                arr[i] = i + 1;
            }
            return arr;
        }
    }
}
